﻿using _3DTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;

namespace CPPEI.WPF
{
    public partial class ViewContainer
    {
        Viewport3D _3dViewport;

        private MeshGeometry3D _3dPlaneMesh;

        private List<ModelVisual3D> _3dVisual3dList;

        private Grid _3dPanel;

        SwitchEffect _switchEffect;

        /// <summary>
        /// 摄像机所在的位置
        /// </summary>
        private Point3D _3dCameraPos;

        /// <summary>
        /// 3d显示的动画对象
        /// </summary>
        private Storyboard _3dStorybard;
        private bool _3dIsStoryboardRunning;

        /// <summary>
        /// (second)
        /// </summary>
        private double _switchEffectDuration = 0.5d;

        private void Init3D()
        {
            if (_3dViewport == null)
            {
                _3dStorybard = new Storyboard();
                _3dStorybard.Completed += sb_Completed;

                _3dVisual3dList = new List<ModelVisual3D>();

                double width = this.ActualWidth;
                double height = this.ActualHeight;
                _3dPlaneMesh = new MeshGeometry3D();
                //_plane.Positions.Add(new Point3D(-1, 1, 0));
                //_plane.Positions.Add(new Point3D(-1, -1, 0));
                //_plane.Positions.Add(new Point3D(1, -1, 0));
                //_plane.Positions.Add(new Point3D(1, 1, 0));
                _3dPlaneMesh.Positions.Add(new Point3D(-1.0d * (width / 2), (height / 2), 0));
                _3dPlaneMesh.Positions.Add(new Point3D(-1.0d * (width / 2), -(height / 2), 0));
                _3dPlaneMesh.Positions.Add(new Point3D((width / 2), -(height / 2), 0));
                _3dPlaneMesh.Positions.Add(new Point3D((width / 2), (height / 2), 0));
                _3dPlaneMesh.TextureCoordinates.Add(new System.Windows.Point(0, 0));
                _3dPlaneMesh.TextureCoordinates.Add(new System.Windows.Point(0, 1));
                _3dPlaneMesh.TextureCoordinates.Add(new System.Windows.Point(1, 1));
                _3dPlaneMesh.TextureCoordinates.Add(new System.Windows.Point(1, 0));
                _3dPlaneMesh.TriangleIndices.Add(0);
                _3dPlaneMesh.TriangleIndices.Add(1);
                _3dPlaneMesh.TriangleIndices.Add(2);
                _3dPlaneMesh.TriangleIndices.Add(0);
                _3dPlaneMesh.TriangleIndices.Add(2);
                _3dPlaneMesh.TriangleIndices.Add(3);
                _3dViewport = new Viewport3D();
                _3dCameraPos = new System.Windows.Media.Media3D.Point3D(0, 0, width / 2 / Math.Tan(Math.PI / 8));

                _3dViewport.Camera = new PerspectiveCamera(_3dCameraPos,
                    new System.Windows.Media.Media3D.Vector3D(0, 0, 0 - _3dCameraPos.Z),
                    new System.Windows.Media.Media3D.Vector3D(0, 1, 0),
                    45);
                ModelVisual3D lightModel = new ModelVisual3D();
                //DirectionalLight light = new DirectionalLight(System.Windows.Media.Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF),
                //    new Vector3D(0, 0, -1));
                AmbientLight light = new AmbientLight(Color.FromArgb(0xff, 0xff, 0xff, 0xff));
                lightModel.Content = light;
                _3dViewport.Children.Add(lightModel);

                _3dPanel = new Grid();
                _3dPanel.Background = new SolidColorBrush(Colors.White);
                _3dPanel.Children.Add(_3dViewport);

                _container = new Grid();
                this.Children.Add(_container);
                this.Children.Add(_3dPanel);
            }
        }

        private void Resize3d()
        {
            if (_3dViewport != null)
            {
                double width = this.ActualWidth;
                double height = this.ActualHeight;

                _3dPlaneMesh.Positions.Clear();
                _3dPlaneMesh.Positions.Add(new Point3D(-1.0d * (width / 2), (height / 2), 0));
                _3dPlaneMesh.Positions.Add(new Point3D(-1.0d * (width / 2), -(height / 2), 0));
                _3dPlaneMesh.Positions.Add(new Point3D((width / 2), -(height / 2), 0));
                _3dPlaneMesh.Positions.Add(new Point3D((width / 2), (height / 2), 0));

                _3dViewport.Camera = new PerspectiveCamera(new System.Windows.Media.Media3D.Point3D(0, 0, width / 2 / Math.Tan(Math.PI / 8)),
                    new System.Windows.Media.Media3D.Vector3D(0, 0, -(width / 2 / Math.Tan(Math.PI / 8))),
                    new System.Windows.Media.Media3D.Vector3D(0, 1, 0),
                    45);
            }
        }

        private InteractiveVisual3D Create(View view, out Storyboard storyboard3D)
        {
            InteractiveVisual3D iav3d = new InteractiveVisual3D();
            Transform3DGroup tf3dGroup = new Transform3DGroup();
            TranslateTransform3D ttf3d = new TranslateTransform3D(0, 0, 0);
            RotateTransform3D rtf3d = new RotateTransform3D();
            AxisAngleRotation3D aar3d = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 30);
            rtf3d.Rotation = aar3d;
            tf3dGroup.Children.Add(rtf3d);
            tf3dGroup.Children.Add(ttf3d);
            iav3d.Transform = tf3dGroup;
            iav3d.Geometry = _3dPlaneMesh;
            iav3d.Visual = view;

            storyboard3D = new Storyboard();
            DoubleAnimation animation = new DoubleAnimation();
            animation.From = 30;
            animation.To = 0;
            animation.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(animation, iav3d);
            Storyboard.SetTargetProperty(animation, new System.Windows.PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"));
            storyboard3D.Children.Add(animation);
            //storyboard3D.Begin(this);

            return iav3d;
        }

        RenderTargetBitmap RenderVisaulToBitmap(Visual vsual, int width, int height)
        {
            var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
            rtb.Render(vsual);

            return rtb;
        }

        private ModelVisual3D CreateInGeometryModel3D(View view, ref Storyboard storyboard3D)
        {
            DiffuseMaterial material = new DiffuseMaterial(new ImageBrush(view.Snapshot));

            ModelVisual3D mv3d = new ModelVisual3D();

            GeometryModel3D v3d = new GeometryModel3D();
            v3d.Geometry = _3dPlaneMesh;
            v3d.Material = material;
            v3d.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));
            mv3d.Content = v3d;

            Transform3DGroup tf3dGroup = new Transform3DGroup();
            TranslateTransform3D ttf3d = new TranslateTransform3D(0, 0, 0);
            RotateTransform3D rtf3d = new RotateTransform3D();
            AxisAngleRotation3D aar3d = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 30);
            rtf3d.Rotation = aar3d;
            tf3dGroup.Children.Add(rtf3d);
            tf3dGroup.Children.Add(ttf3d);
            mv3d.Transform = tf3dGroup;

            DoubleAnimation animation = new DoubleAnimation();
            animation.From = 30;
            animation.To = 0;
            animation.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(animation, mv3d);
            Storyboard.SetTargetProperty(animation, new System.Windows.PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"));
            storyboard3D.Children.Add(animation);

            DoubleAnimation animationMoveIn = new DoubleAnimation();
            animationMoveIn.From = view.ActualWidth / 2;
            animationMoveIn.To = 0;
            animationMoveIn.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(animationMoveIn, mv3d);
            Storyboard.SetTargetProperty(animationMoveIn, new System.Windows.PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)"));
            storyboard3D.Children.Add(animationMoveIn);
            //storyboard3D.Begin(this);

            return mv3d;
        }

        private ModelVisual3D CreateOutGeometryModel3D(View view, ref Storyboard storyboard3D)
        {
            DiffuseMaterial material = new DiffuseMaterial(new ImageBrush(view.Snapshot));

            ModelVisual3D mv3d = new ModelVisual3D();

            GeometryModel3D v3d = new GeometryModel3D();
            v3d.Geometry = _3dPlaneMesh;
            v3d.Material = material;
            v3d.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));
            mv3d.Content = v3d;

            Transform3DGroup tf3dGroup = new Transform3DGroup();
            TranslateTransform3D ttf3d = new TranslateTransform3D(0, 0, 0);
            RotateTransform3D rtf3d = new RotateTransform3D();
            AxisAngleRotation3D aar3d = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 30);
            rtf3d.Rotation = aar3d;
            tf3dGroup.Children.Add(rtf3d);
            tf3dGroup.Children.Add(ttf3d);
            mv3d.Transform = tf3dGroup;

            DoubleAnimation animation = new DoubleAnimation();
            animation.From = 0;
            animation.To = 30;
            animation.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(animation, mv3d);
            Storyboard.SetTargetProperty(animation, new System.Windows.PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"));
            storyboard3D.Children.Add(animation);

            DoubleAnimation animationMoveIn = new DoubleAnimation();
            animationMoveIn.From = 0;
            animationMoveIn.To = -view.ActualWidth / 2;
            animationMoveIn.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(animationMoveIn, mv3d);
            Storyboard.SetTargetProperty(animationMoveIn, new System.Windows.PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)"));
            storyboard3D.Children.Add(animationMoveIn);
            //storyboard3D.Begin(this);

            return mv3d;
        }
    }
}
